import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:viser_remit/core/helper/shared_preference_helper.dart';
import 'package:viser_remit/core/helper/string_format_helper.dart';
import 'package:viser_remit/core/utils/my_strings.dart';
import 'package:viser_remit/core/utils/url_container.dart';
import 'package:viser_remit/data/model/dash_board/dashboard_response_model.dart';
import 'package:viser_remit/data/model/general_setting/general_setting_response_model.dart';
import 'package:viser_remit/data/model/global/response_model/response_model.dart';
import 'package:viser_remit/data/model/home/country_info_model.dart' as countryModel;
import 'package:viser_remit/data/model/kyc/kyc_response_model.dart';
import 'package:viser_remit/data/model/profile/profile_response_model.dart';
import 'package:viser_remit/data/model/send_money/servicelist_response_model.dart';
import 'package:viser_remit/data/repo/home/home_repo.dart';

import '../../../core/route/route.dart';
import '../../../view/components/snack_bar/show_custom_snackbar.dart';
import '../../model/dash_board/dashboard_response_model.dart' as dashboard;

class HomeController extends GetxController {
  HomeRepo homeRepo;
  HomeController({required this.homeRepo});
  int sendingCountryId = 0;
  int receivingCountryId = 0;
  int conversionCurrencyRate = 0;
  bool isLoading = true;
  String imagePath = "${UrlContainer.domainUrl}/assets/images/country";
  String defaultCurrency = "";
  String defaultCurrencySymbol = "";

  String payableAmount = '';

  String status = '1';
  String isKycVerified = '1';

  int currentLanguage = 0;

  countryModel.SendingCountries selectedSendCountry = countryModel.SendingCountries(id: -1, currency: "USD", rate: '0.00');
  countryModel.ReceivingCountries selectedReceiveCountry = countryModel.ReceivingCountries(id: -1, currency: 'USD', rate: '0.00');
  countryModel.ConversionRate conversionRate = countryModel.ConversionRate();

  countryModel.CountryDeliveryMethods defaultDeliveryMethod = countryModel.CountryDeliveryMethods(id: -1, deliveryMethod: countryModel.DeliveryMethod(name: MyStrings.selectOne));
  countryModel.CountryDeliveryMethods agentDeliveryMethod = countryModel.CountryDeliveryMethods(id: -1, deliveryMethod: countryModel.DeliveryMethod(name: MyStrings.agent));
  late countryModel.CountryDeliveryMethods selectedDeliveryMethod = defaultDeliveryMethod;

  List<countryModel.CountryDeliveryMethods> deliveryMethodList = [];

  GeneralSettingResponseModel generalSettingResponseModel = GeneralSettingResponseModel();

  List<countryModel.SendingCountries> sendingCountryList = [];
  List<countryModel.SendingCountries> allSendingCountryList = [];
  List<countryModel.ReceivingCountries> receivingCountryList = [];
  List<countryModel.ReceivingCountries> allReceivingCountryList = [];
  bool submitLoading = false;
  int? sendCurrencyID;
  int? buyCurrencyID;

  TextEditingController sendingAmountController = TextEditingController(text: '');
  TextEditingController receivingAmountController = TextEditingController(text: '');

  void loadAllData({bool fromHome = false}) async {
    isLoading = true;
    update();
    if (fromHome == true) {
      selectedSendCountry = countryModel.SendingCountries(id: -1, currency: "USD", rate: '0.00');
      selectedReceiveCountry = countryModel.ReceivingCountries(id: -1, currency: 'USD', rate: '0.00');
      sendingAmountController.text = '0.0';
      receivingAmountController.text = '0.0';
    }
    setSelectedLanguage(homeRepo.apiClient.sharedPreferences.getString(SharedPreferenceHelper.languageName).toString());
    print("language name$selectedLanguage");
    await loadCountryData();
    await loadDashBoardData();
    await loadUserProfileData();

    isLoading = false;
    update();
  }

  Future<void> loadCountryData() async {
    ResponseModel model = await homeRepo.getCountryData();
    deliveryMethodList.clear();

    deliveryMethodList.add(defaultDeliveryMethod);
    selectedDeliveryMethod = deliveryMethodList[0];
    if (model.statusCode == 200) {
      countryModel.CountryInfoModel countryInfoModel = countryModel.CountryInfoModel.fromJson(jsonDecode(model.responseJson));

      List<countryModel.SendingCountries>? tempSendingCountryList = countryInfoModel.data?.sendingCountries;

      if (tempSendingCountryList != null && tempSendingCountryList.isNotEmpty) {
        sendingCountryList.clear();
        sendingCountryList.addAll(tempSendingCountryList);
        allSendingCountryList.addAll(tempSendingCountryList);
      }

      List<countryModel.ReceivingCountries>? tempReceivingCountryList = countryInfoModel.data?.receivingCountries;

      if (tempReceivingCountryList != null && tempReceivingCountryList.isNotEmpty) {
        receivingCountryList.clear();
        List<countryModel.ReceivingCountries> allUniqueReceivingCountryList = removeDuplicateReceivingCountry(tempReceivingCountryList);
        allReceivingCountryList.addAll(allUniqueReceivingCountryList);
        receivingCountryList.addAll(allUniqueReceivingCountryList);
      }
    } else {
      CustomSnackBar.error(errorList: [model.message]);
    }
  }

  String balance = '00.00';
  String sendMoneyAmount = '00.00';
  String sendMoneyInitiated = '00.00';
  String sendMoneyPending = '00.00';
  String paymentPending = '00.00';
  String paymentRejected = '00.00';

  List<Transfer> recentTransactionList = [];

  Future<void> loadDashBoardData() async {
    ResponseModel model = await homeRepo.getDashBoardData();

    if (model.statusCode == 200) {
      dashboard.DashboardResponseModel dashboardResponseModel = dashboard.DashboardResponseModel.fromJson(jsonDecode(model.responseJson));

      recentTransactionList.clear();

      if (dashboardResponseModel.data?.widget != null) {
        balance = Converter.formatNumber(dashboardResponseModel.data?.widget?.balance.toString() ?? "0.00");
        sendMoneyAmount = Converter.formatNumber(dashboardResponseModel.data?.widget?.sendMoneyAmount.toString() ?? "0.00");
        sendMoneyPending = Converter.formatNumber(dashboardResponseModel.data?.widget?.sendMoneyPending.toString() ?? "0.00");
        sendMoneyInitiated = Converter.formatNumber(dashboardResponseModel.data?.widget?.sendMoneyInitiated.toString() ?? "0.00");
        paymentRejected = Converter.formatNumber(dashboardResponseModel.data?.widget?.paymentRejected.toString() ?? "0.00");
        paymentPending = Converter.formatNumber(dashboardResponseModel.data?.widget?.paymentPending.toString() ?? "0.00");
      }

      if (dashboardResponseModel.data?.transfers != null && dashboardResponseModel.data!.transfers!.isNotEmpty) {
        recentTransactionList.addAll(dashboardResponseModel.data!.transfers!);
      }
    } else {
      CustomSnackBar.error(errorList: [model.message]);
    }
  }

  String selectedDeliveryMethodId = '-1';

  bool isAgentSelected = false;

  setSelectedDeliveryMethod(countryModel.CountryDeliveryMethods value) {
    if (value.deliveryMethod?.name.toString() == MyStrings.agent) {
      isAgentSelected = true;
    } else {
      isAgentSelected = false;
    }

    selectedDeliveryMethod = value;
    selectedDeliveryMethodId = value.deliveryMethodId ?? '-1';
    loadServiceList(value.deliveryMethodId.toString());
    update();
  }

  Services selectedServices = Services(name: MyStrings.selectOne, id: -1);
  Services defaultService = Services(name: MyStrings.selectOne, id: -1);

  setSelectedServiceMethod(Services value) {
    selectedServices = value;
    // serviceDynamicFormList.clear();
    formatKycData(value.form?.mainList);
    // formatKycData(value.form.);
    update();
  }

  bool enableSendMoneyScreenOptionalItem = true;

  setSendMoneyScreenOptionalItem(bool value) {
    enableSendMoneyScreenOptionalItem = value;
    update();
  }

  List<Services> serviceList = [];

  bool isServiceLoading = false;
  Future<void> loadServiceList(String deliveryMethodId) async {
    isServiceLoading = true;
    update();

    ResponseModel model = await homeRepo.getServiceList(selectedReceiveCountry.id.toString(), deliveryMethodId);

    serviceList.clear();

    serviceList.insert(0, defaultService);
    setSelectedServiceMethod(serviceList[0]);

    if (model.statusCode == 200) {
      ServicelistResponseModel serviceListResponseModel = ServicelistResponseModel.fromJson(jsonDecode(model.responseJson));

      if (serviceListResponseModel.status?.toLowerCase() == 'success') {
        List<Services>? tempServiceList = serviceListResponseModel.data?.services;
        if (tempServiceList != null && tempServiceList.isNotEmpty) {
          serviceList.addAll(tempServiceList);
        }
      } else {
        CustomSnackBar.error(errorList: ['']);
      }
    } else {
      CustomSnackBar.error(errorList: [model.message]);
    }

    isServiceLoading = false;
    update();
  }

  List<KycFormModel> serviceDynamicFormList = [];
  String selectOne = MyStrings.selectOne;

  formatKycData(List<KycFormModel>? tList) async {
    serviceDynamicFormList.clear();

    if (tList != null && tList.isNotEmpty) {
      try {
        serviceDynamicFormList.clear();
        for (var element in tList) {
          if (element.type == 'select') {
            bool? isEmpty = element.options?.isEmpty;
            bool empty = isEmpty ?? true;
            if (element.options != null && empty != true) {
              element.options?.insert(0, selectOne);
              element.selectedValue = element.options?.first;
              serviceDynamicFormList.add(element);
            }
          } else {
            serviceDynamicFormList.add(element);
          }
        }
      } catch (e) {
        if (kDebugMode) {
          print(e.toString());
        }
      }
    }
  }

  void changeCurrentLanguage(int index) {
    currentLanguage = index;
    update();
  }

  bool showDashBoardAllCard = false;
  changeDashBoardCardStatus(bool status) {
    showDashBoardAllCard = status;
    update();
  }

  double sendingAmount = 0.0;
  double receiveAmount = 0.0;

  String getSendingAmountDataValidation() {
    String sendingAmountText = sendingAmountController.text.trim();
    String receivingAmountText = receivingAmountController.text.trim();

    // Check if the sending amount is a valid number
    if (double.tryParse(sendingAmountText) != null) {
      double sendingAmount = double.parse(sendingAmountText);

      // Check if the sending amount is greater than 0
      if (sendingAmount <= 0) {
        return MyStrings.sendingAmountMustGreaterThanZeroMSg;
      }
    } else {
      return MyStrings.enterValidAmount;
    }

    // Check if the receiving amount is a valid number
    if (double.tryParse(receivingAmountText) != null) {
      double receivingAmount = double.parse(receivingAmountText);

      // Check if the receiving amount is greater than 0
      if (receivingAmount <= 0) {
        return MyStrings.receivingMustGreaterThanZeroMSg;
      }
    } else {
      return MyStrings.enterValidAmount;
    }

    // If both amounts are valid, return an empty string to indicate success
    return '';
  }

  void setSendCountry(countryModel.SendingCountries selectedSendingCountry, String sendCountryId) {
    sendingCountryId = 0;
    sendingCountryId = int.tryParse(sendCountryId) ?? 0;
    selectedSendCountry = selectedSendingCountry;
    receivingCountryList.clear();

    List<countryModel.ReceivingCountries> allUniqueReceivingCountryList = removeDuplicateReceivingCountry(allReceivingCountryList);

    for (var element in allUniqueReceivingCountryList) {
      if (element.currency?.toLowerCase() != selectedSendingCountry.currency?.toLowerCase()) {
        receivingCountryList.add(element);
      }
    }

    if (sendingAmountController.text.trim().isNotEmpty) {
      receiveCurrencyExchangeRateCalculate(sendingAmountController.text.trim(), setSendCountry: true);
    }

    update();
  }

  List<countryModel.ReceivingCountries> removeDuplicateReceivingCountry(List<countryModel.ReceivingCountries> items) {
    List<countryModel.ReceivingCountries> uniqueItems = []; // uniqueList
    var uniqueIDs = items.map((e) => e.currency).toSet();
    for (var e in uniqueIDs) {
      uniqueItems.add(items.firstWhere((i) => i.currency == e));
    }
    return uniqueItems;
  }

  List<countryModel.SendingCountries> removeDuplicateSendingCountry(List<countryModel.SendingCountries> items) {
    List<countryModel.SendingCountries> uniqueItems = [];
    var uniqueIDs = items.map((e) => e.currency).toSet();
    for (var e in uniqueIDs) {
      uniqueItems.add(items.firstWhere((i) => i.currency == e));
    }
    return uniqueItems;
  }

  void setReceiveCountry(countryModel.ReceivingCountries selectedReceivingCountry, String recieveCountryId) {
    receivingCountryId = int.tryParse(recieveCountryId.toString()) ?? 0;
    deliveryMethodList.clear();

    selectedReceiveCountry = selectedReceivingCountry;

    List<countryModel.CountryDeliveryMethods>? tempDeliveryMethodList = selectedReceivingCountry.countryDeliveryMethods;

    deliveryMethodList.add(defaultDeliveryMethod);

    if (tempDeliveryMethodList != null && tempDeliveryMethodList.isNotEmpty) {
      if (selectedReceiveCountry.hasAgent.toString() == '1') {
        deliveryMethodList.add(agentDeliveryMethod);
      }

      deliveryMethodList.addAll(tempDeliveryMethodList);
      setSelectedDeliveryMethod(deliveryMethodList[0]);
    } else {
      deliveryMethodList.add(agentDeliveryMethod);
      setSelectedDeliveryMethod(deliveryMethodList[0]);
    }

    sendingCountryList.clear();

    List<countryModel.SendingCountries> allUniqueSendingCountryList = removeDuplicateSendingCountry(allSendingCountryList);

    for (var element in allUniqueSendingCountryList) {
      if (element.currency?.toLowerCase() != selectedReceivingCountry.currency?.toLowerCase()) {
        sendingCountryList.add(element);
      }
    }

    if (receivingAmountController.text.trim().isNotEmpty) {
      sendCurrencyExchangeRateCalculate(receivingAmountController.text.trim(), setSendCountry: true);
    } else {
      receivingAmountController.text = '0.0';
    }

    update();
  }

  String getInitialCurrencyRate() {
    double receivingCurrencyRate = double.tryParse(selectedReceiveCountry.rate.toString()) ?? 0;
    double sendingCurrencyRate = double.tryParse(selectedSendCountry.rate.toString()) ?? 0;
    double initialCurrencyRate = (receivingCurrencyRate / sendingCurrencyRate);

    return Converter.formatNumber(initialCurrencyRate != 0 ? initialCurrencyRate.toString() : conversionCurrencyRate.toString(), precision: 2);
  }

  double getRateByCountryIds(
    List<countryModel.ConversionRate>? conversionRates,
  ) {
    if (conversionRates != null) {
      for (var rate in conversionRates) {
        if (rate.fromCountry == sendingCountryId.toString() && rate.toCountry == receivingCountryId.toString()) {
          return double.tryParse(rate.rate ?? "0") ?? 0;
        }
      }
    }
    return 0;
  }

  void sendCurrencyExchangeRateCalculate(String value, {bool setSendCountry = false}) {
    if (setSendCountry == true) {
      double inputValue = double.tryParse(value) ?? 0;

      double receivingCurrencyRate = double.tryParse(selectedReceiveCountry.rate?.toString() ?? "0") ?? 0;
      double sendingCurrencyRate = double.tryParse(selectedSendCountry.rate?.toString() ?? "0") ?? 0;

      double amount = (inputValue * sendingCurrencyRate) / receivingCurrencyRate;

      if (amount.toString() == 'NaN') {
        amount = 0.00;
      }
      sendingAmountController.text = Converter.formatNumber(amount.toString(), precision: 2);
    } else {
      double inputValue = double.tryParse(value) ?? 0;
      double receivingCurrencyRate = double.tryParse(selectedReceiveCountry.rate.toString()) ?? 0;
      double sendingCurrencyRate = getRateByCountryIds(
        selectedSendCountry.conversionRates,
      );
      double sendingBaseCurrencyRate = double.tryParse(selectedSendCountry.rate.toString()) ?? 0;
      conversionCurrencyRate = int.tryParse(sendingCurrencyRate.toString()) ?? 0;

      double amount = sendingCurrencyRate.toString() != "0.0" ? (inputValue * receivingCurrencyRate) / sendingCurrencyRate : (inputValue * receivingCurrencyRate) / sendingBaseCurrencyRate;
      update();
      if (amount.toString() == 'NaN') {
        amount = 0.00;
      }

      if (selectedReceiveCountry.id != -1) {
        receivingAmountController.text = Converter.formatNumber(amount.toString(), precision: 2);
      }
    }
    update();
  }

  void receiveCurrencyExchangeRateCalculate(String value, {bool setSendCountry = false}) {
    if (setSendCountry == true) {
      double inputValue = double.tryParse(value) ?? 0;

      double receivingCurrencyRate = double.tryParse(selectedReceiveCountry.rate?.toString() ?? "0") ?? 0;
      double sendingCurrencyRate = double.tryParse(selectedSendCountry.rate?.toString() ?? "0") ?? 0;

      double amount = (inputValue * receivingCurrencyRate) / sendingCurrencyRate;
      if (amount.toString() == 'NaN') {
        amount = 0.00;
      }

      receivingAmountController.text = Converter.formatNumber(amount.toString(), precision: 2);
    } else {
      double inputValue = double.tryParse(value) ?? 0;

      double receivingCurrencyRate = double.tryParse(selectedReceiveCountry.rate?.toString() ?? "0") ?? 0;
      double sendingCurrencyRate = double.tryParse(selectedSendCountry.rate?.toString() ?? "0") ?? 0;

      double amount = (inputValue * sendingCurrencyRate) / receivingCurrencyRate;

      if (amount.toString() == 'NaN') {
        amount = 0.00;
      }

      if (selectedSendCountry.id != -1) {
        sendingAmountController.text = Converter.formatNumber(amount.toString(), precision: 2);
      }
    }

    update();
  }

  String getCharge() {
    //todo
    String inputText = sendingAmountController.text.trim();
    if (inputText.isEmpty) {
      return '0.00';
    }
    try {
      double charge = 0.00;
      double sendingValue = double.parse(inputText);
      if (selectedDeliveryMethod.charge == null && !isAgentSelected) {
        charge = 0.00;
      } else if (isAgentSelected) {
        double rateDifference = double.parse(selectedSendCountry.rate?.toString() ?? '0.00') / double.parse(selectedReceiveCountry.rate?.toString() ?? '0.00');
        double fixedCharge = double.parse(homeRepo.apiClient.getGSData().data?.generalSetting?.agentCharges?.fixedCharge.toString() ?? '0.00') * rateDifference;
        double percentageCharge = sendingValue * double.parse(homeRepo.apiClient.getGSData().data?.generalSetting?.agentCharges?.percentCharge.toString() ?? '0.00') / 100;
        charge = fixedCharge + percentageCharge;
      } else {
        double rateDifference = double.parse(selectedSendCountry.rate?.toString() ?? '0.00') / double.parse(selectedReceiveCountry.rate?.toString() ?? '0.00');
        double fixedCharge = double.parse(selectedDeliveryMethod.charge?.fixedCharge?.toString() ?? '0.00') * rateDifference;
        double percentageCharge = sendingValue * double.parse(selectedDeliveryMethod.charge?.percentCharge?.toString() ?? '0.00') / 100;
        charge = fixedCharge + percentageCharge;
      }
      return Converter.formatNumber(charge.toString(), precision: 2);
    } catch (e) {
      if (kDebugMode) {
        print("$e");
      }
      return MyStrings.invalid.tr;
    }
  }

  String countPayableAmount() {
    String inputText = sendingAmountController.text.trim();
    if (inputText.isEmpty) {
      return '0.00';
    }
    try {
      double sendingValue = double.parse(inputText);

      double payableAmount = sendingValue + double.parse(getCharge());
      return Converter.formatNumber(payableAmount.toString(), precision: 2);
    } catch (e) {
      if (kDebugMode) {
        print("$e");
      }
      return MyStrings.invalid.tr;
    }
  }

  List<String> hasError() {
    List<String> errorList = [];
    errorList.clear();

    for (var element in serviceDynamicFormList) {
      if (element.isRequired == 'required') {
        if (element.type == 'checkbox') {
          if (element.cbSelected == null) {
            errorList.add('${element.name} ${MyStrings.isRequired}');
          }
        } else if (element.type == 'file') {
          if (element.imageFile == null) {
            errorList.add('${element.name} ${MyStrings.isRequired}');
          }
        } else {
          if (element.selectedValue == '' || element.selectedValue == selectOne) {
            errorList.add('${element.name} ${MyStrings.isRequired}');
          }
        }
      }
    }

    return errorList;
  }

  void changeSelectedValue(value, int index) {
    serviceDynamicFormList[index].selectedValue = value;
    update();
  }

  void changeSelectedRadioBtnValue(int listIndex, int selectedIndex) {
    serviceDynamicFormList[listIndex].selectedValue = serviceDynamicFormList[listIndex].options?[selectedIndex];
    update();
  }

  void changeSelectedCheckBoxValue(int listIndex, String value) {
    List<String> list = value.split('_');
    int index = int.parse(list[0]);
    bool status = list[1] == 'true' ? true : false;

    List<String>? selectedValue = serviceDynamicFormList[listIndex].cbSelected;

    if (selectedValue != null) {
      String? value = serviceDynamicFormList[listIndex].options?[index];
      if (status) {
        if (!selectedValue.contains(value)) {
          selectedValue.add(value!);
          serviceDynamicFormList[listIndex].cbSelected = selectedValue;
          update();
        }
      } else {
        if (selectedValue.contains(value)) {
          selectedValue.removeWhere((element) => element == value);
          serviceDynamicFormList[listIndex].cbSelected = selectedValue;
          update();
        }
      }
    } else {
      selectedValue = [];
      String? value = serviceDynamicFormList[listIndex].options?[index];
      if (status) {
        if (!selectedValue.contains(value)) {
          selectedValue.add(value!);
          serviceDynamicFormList[listIndex].cbSelected = selectedValue;
          update();
        }
      } else {
        if (selectedValue.contains(value)) {
          selectedValue.removeWhere((element) => element == value);
          serviceDynamicFormList[listIndex].cbSelected = selectedValue;
          update();
        }
      }
    }
  }

  void pickFile(int index) async {
    FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: false, type: FileType.custom, allowedExtensions: ['jpg', 'png', 'jpeg', 'pdf', 'doc', 'docx']);

    if (result == null) return;

    serviceDynamicFormList[index].imageFile = File(result.files.single.path!);
    String fileName = result.files.single.name;
    serviceDynamicFormList[index].selectedValue = fileName;
    update();
    return;
  }

  gotoNextPage() {
    if (getSendingAmountDataValidation() == '') {
      if (selectedSendCountry.id == -1) {
        CustomSnackBar.error(errorList: [MyStrings.selectSendingCountry]);
      } else if (selectedReceiveCountry.id == -1) {
        CustomSnackBar.error(errorList: [MyStrings.selectRecivingCountry]);
      } else if (sendingAmountController.text.isEmpty) {
        CustomSnackBar.error(errorList: [MyStrings.enterValidAmount]);
      } else {
        Get.toNamed(RouteHelper.senderScreen);
      }
    } else {
      CustomSnackBar.error(errorList: [getSendingAmountDataValidation()]);
    }
  }

  String selectedLanguage = MyStrings.english;

  setSelectedLanguage(String value) {
    if (value.toString() != "null") {
      selectedLanguage = value;
    }
    update();
  }

  Future<void> loadUserProfileData() async {
    try {
      ResponseModel responseModel = await homeRepo.getUserInfoData();

      if (responseModel.statusCode == 200) {
        ProfileResponseModel model = ProfileResponseModel.fromJson(jsonDecode(responseModel.responseJson));
        if (model.status == 'success') {
          await homeRepo.apiClient.sharedPreferences.setString(SharedPreferenceHelper.userPhoneNumberKey, model.data?.user?.mobile ?? '');
          await homeRepo.apiClient.sharedPreferences.setString(SharedPreferenceHelper.userNameKey, model.data?.user?.username ?? '');
          await homeRepo.apiClient.sharedPreferences.setString(SharedPreferenceHelper.userEmailKey, model.data?.user?.email ?? '');
          isKycVerified = model.data?.user?.kv ?? '1';
        } else {}
      } else {}
    } catch (e) {
      print(e.toString());
    }
  }
}
